package cliente.controle;

import java.awt.HeadlessException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;

import cliente.bancoCliente.BancoCliente;
import cliente.modelo.Cliente;
import cliente.modelo.Gerente;
import cliente.modelo.TipoPessoa;
import cliente.vista.ClienteView;
import cliente.vista.LoginView;
import cliente.vista.VerClientesView;
import cliente.vista.VisualizarClienteView;


public class ClienteControlador {
	
	// Ações para controlar Views
	
	public static void logar(LoginView loginView, String login, String senha) {
		try {
			// pede para logar no servidor
			BancoCliente.escreveServidor("logarCliente");
			BancoCliente.escreveServidor(login + "-" + Criptografa.md5(senha));
			
			String inputLine = BancoCliente.getLineServidor(); // pega a mensagem para ver se foi possivel logar com sucesso
			
			if (inputLine.equals(Criptografa.md5("precisa logar"))) {
				loginView.zeraTelaLogin();
				JOptionPane.showMessageDialog(loginView.getTela(), "login/senha incorretos");
			}
			else if (inputLine.equals(Criptografa.md5("logado"))) {
				// Atualiza o id do usuario logado no sistema
				Sistema sistema = Sistema.getUnicaInstancia();
				sistema.setAtualId( Integer.parseInt(BancoCliente.getLineServidor()) );
				// Chama a view do cliente e fecha a do login
				loginView.getTela().dispose();
				ClienteView clienteView = new ClienteView();
				clienteView.iniciaTela();
			}
		} catch (NumberFormatException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (HeadlessException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	// Métodos para VerClientesView

	public static void atualizaDadosEmCampoClientes(DefaultListModel campoClientesConteudo, ArrayList<Cliente> todosClientes,
			HashMap<String, Integer> mapaNomeId) throws SQLException, IOException {
		todosClientes = getAll();
		// Os clears ajudarão a atualizar a view
		campoClientesConteudo.clear();
		mapaNomeId.clear();
		
		Sistema sistema = Sistema.getUnicaInstancia();
		int idGerente = sistema.getAtualId();
		for (int i = 0; i < todosClientes.size(); i++)
		{
			if (todosClientes.get(i).getGerenteId() == idGerente)
			{
				String nome = todosClientes.get(i).getNome();
				int id = todosClientes.get(i).getId();
				campoClientesConteudo.addElement(nome);
				mapaNomeId.put(nome, id); // a cada nome na lista que será exibida, é associado o id do cliente que está no BD.
			}
		}
	}
	
	public static void deletaCliente(JFrame tela, JList campoClientes,
			HashMap<String, Integer> mapaNomeId, DefaultListModel campoClientesConteudo,
			JButton deleteButton) {
		int index = campoClientes.getSelectedIndex();
		if(index < 0){
			JOptionPane.showMessageDialog(tela, "Nenhum cliente selecionado");
			return;
		}
		
		//Pega o id do cliente no BD
		String nome = campoClientes.getSelectedValue().toString();
		int id =  mapaNomeId.get(nome);
		
		delete(id); // deleta o cliente
			
		campoClientesConteudo.remove(index);
		
		int size = campoClientesConteudo.getSize();
		
		if (size == 0) { // Se não tem nenhum cliente não deixa poder clicar no botão de deletar
			deleteButton.setEnabled(false);
		} else {
			if (index == campoClientesConteudo.getSize()) {
				index--;
			}
			
			campoClientes.setSelectedIndex(index);
			campoClientes.ensureIndexIsVisible(index);
		}
	}
	
	public static void alterarCliente(VerClientesView verClientesView, VisualizarClienteView visualizarClienteView,
			JFrame tela, Cliente cliente, String nome, String login, String senha, String email, String cpfCnpj, Gerente gerente) {
		if (Criptografa.md5(senha).equals(cliente.getSenha()) && ((exists(login)==false) || login.equals(cliente.getLogin())))
		{
			ClienteControlador.atualiza(cliente.getId(), gerente.getId(), nome, 
					login, email, cliente.getSenha(), cliente.getTipoPessoa(), cpfCnpj);
			verClientesView.atualiza();
			visualizarClienteView.atualiza();
			tela.dispose();
		}
		else
		{
			if (exists(login))
			{
				JOptionPane.showMessageDialog(tela, "o login do cliente ja existe");
			}
			else{
				JOptionPane.showMessageDialog(tela, "senha não confere");				
			}
		}
	}
	
	// Ações de banco de dados
	
	public static void cria(int gerenteId, String nome, String login, String email, String senha,
			TipoPessoa tipoDePessoa, String cpfCnpj) throws SQLException {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.cria que está no servidor, escrevendo por socket os parâmetros
		sistema.escreveServidor("ClienteControlador");
		sistema.escreveServidor("cria");
		sistema.escreveServidor(gerenteId);
		sistema.escreveServidor(nome);
		sistema.escreveServidor(login);
		sistema.escreveServidor(email);
		sistema.escreveServidor(senha);
		sistema.escreveServidor( (tipoDePessoa == TipoPessoa.FISICA) ? "FISICA" : "JURIDICA");
		sistema.escreveServidor(cpfCnpj);
	}
	
	public static void atualiza(int id, int gerenteId, String nome, String login, String email, String senha,
			TipoPessoa tipoDePessoa, String cpfCnpj ){
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.atualiza que está no servidor, escrevendo por socket os parâmetros
		sistema.escreveServidor("ClienteControlador");
		sistema.escreveServidor("atualiza");
		sistema.escreveServidor(id);
		sistema.escreveServidor(gerenteId);
		sistema.escreveServidor(nome);
		sistema.escreveServidor(login);
		sistema.escreveServidor(email);
		sistema.escreveServidor(senha);
		sistema.escreveServidor( (tipoDePessoa == TipoPessoa.FISICA) ? "FISICA" : "JURIDICA");
		sistema.escreveServidor(cpfCnpj);
	}
	
	private static Cliente getCliente(Sistema sistema) throws IOException {
		// retorna um cliente pegando os seus dados do servidor
		
		String param = sistema.getLineServidor(); // verifica que o servidor não retornou a string "null"
		if(param == "null") return null;
		
		int id = Integer.parseInt(param);
		int gerenteId = Integer.parseInt(sistema.getLineServidor());
		String nome = sistema.getLineServidor();
		String login = sistema.getLineServidor();
		String email = sistema.getLineServidor();
		String senha = sistema.getLineServidor();
		TipoPessoa tipoPessoa = (sistema.getLineServidor().equalsIgnoreCase("FISICA") ? TipoPessoa.FISICA : TipoPessoa.JURIDICA);
		String cpfCnpj = sistema.getLineServidor();
		
		return new Cliente(id, gerenteId, nome, login, email, senha, tipoPessoa, cpfCnpj);
	}
	
	private static Cliente getCliente(Sistema sistema, int id) throws IOException {
		// retorna um cliente pegando os seus dados do servidor
		int gerenteId = Integer.parseInt(sistema.getLineServidor());
		String nome = sistema.getLineServidor();
		String login = sistema.getLineServidor();
		String email = sistema.getLineServidor();
		String senha = sistema.getLineServidor();
		TipoPessoa tipoPessoa = (sistema.getLineServidor().equalsIgnoreCase("FISICA") ? TipoPessoa.FISICA : TipoPessoa.JURIDICA);
		String cpfCnpj = sistema.getLineServidor();
		
		return new Cliente(id, gerenteId, nome, login, email, senha, tipoPessoa, cpfCnpj);
	}
	
	public static Cliente get(int id) throws NumberFormatException, IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.get que está no servidor, escrevendo por socket os parâmetros
		sistema.escreveServidor("ClienteControlador");
		sistema.escreveServidor("get");
		sistema.escreveServidor(id);
		return getCliente(sistema);
	}


	public static Cliente get(String login, String senha) throws NumberFormatException, IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.get que está no servidor, escrevendo por socket os parâmetros
		sistema.escreveServidor("ClienteControlador");
		sistema.escreveServidor("get");
		sistema.escreveServidor(login);
		sistema.escreveServidor(senha);
		return getCliente(sistema);
	}
	
	public static boolean exists(String login)
	{
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.exists que está no servidor, escrevendo por socket os parâmetros
		sistema.escreveServidor("ClienteControlador");
		sistema.escreveServidor("exists");
		sistema.escreveServidor(login);
		try {
			return sistema.getLineServidor().equalsIgnoreCase("true"); // se for igual a "true" retornará true
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return false;
	}
	
	public static ArrayList<Cliente> getAll() throws SQLException, IOException {
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.getAll que está no servidor, escrevendo por socket os parâmetros
		sistema.escreveServidor("ClienteControlador");
		sistema.escreveServidor("getAll");
		String param;
		ArrayList<Cliente> clientes = new ArrayList<Cliente>(); 
		while( !(param = sistema.getLineServidor()).equalsIgnoreCase("END") )
		{
			int id = Integer.parseInt(param);
			clientes.add(getCliente(sistema, id));
		}
		return clientes;
	}
	
	public static void delete(int id){
		Sistema sistema = Sistema.getUnicaInstancia();
		// Executa o método ClienteControlador.delete que está no servidor, escrevendo por socket os parâmetros
		sistema.escreveServidor("ClienteControlador");
		sistema.escreveServidor("delete");
		sistema.escreveServidor(id);
	}
}
